#include "nasm/instruction/generator.h"
#include "nasm/report/report.h"
#include "nasm/instruction/ADD.h"
#include <algorithm>

namespace dspnasm {

    std::shared_ptr<Instruction> Generator::gen3Op(const std::string &opName, const std::string &funcUnit,
                                                   const std::vector<std::shared_ptr<Operand>> &ops, bool p) {
        std::shared_ptr<Instruction> instruction;
        if (opName == "ADD") {
            instruction = ADD::genAdd(funcUnit, ops, p);
        }
        return instruction;
    }

    std::bitset<5> Generator::computeDst(std::shared_ptr<Operand> op) {
        std::bitset<5> data;
        auto reg = std::dynamic_pointer_cast<SingleRegOp>(op);
        if (reg) {
            if (reg->m_reg >= RegKind::A0 && reg->m_reg <= RegKind::A31) {
                data = static_cast<u32>(reg->m_reg) - static_cast<u32>(RegKind::A0);
            } else if (reg->m_reg >= RegKind::B0 && reg->m_reg <= RegKind::B31) {
                data = static_cast<u32>(reg->m_reg) - static_cast<u32>(RegKind::B0);
            }
            return data;
        }

        auto regs = std::dynamic_pointer_cast<DoubleRegOp>(op);
        if (regs) {
            if (regs->m_regLo >= RegKind::A0 && regs->m_regLo <= RegKind::A31) {
                data = static_cast<u32>(regs->m_regLo) - static_cast<u32>(RegKind::A0);
            } else if (regs->m_regLo >= RegKind::B0 && regs->m_regLo <= RegKind::B31) {
                data = static_cast<u32>(regs->m_regLo) - static_cast<u32>(RegKind::B0);
            }
            return data;
        }
        fatalMacro("指令的dst位解析错误！");
    }

    std::bitset<5> Generator::computeSrc1(std::shared_ptr<Operand> op) {
        std::bitset<5> data;
        auto reg = std::dynamic_pointer_cast<SingleRegOp>(op);
        if (reg) {
            if (reg->m_reg >= RegKind::A0 && reg->m_reg <= RegKind::A31) {
                data = static_cast<u32>(reg->m_reg) - static_cast<u32>(RegKind::A0);
            } else if (reg->m_reg >= RegKind::B0 && reg->m_reg <= RegKind::B31) {
                data = static_cast<u32>(reg->m_reg) - static_cast<u32>(RegKind::B0);
            }
            return data;
        }

        auto regs = std::dynamic_pointer_cast<DoubleRegOp>(op);
        if (regs) {
            if (regs->m_regLo >= RegKind::A0 && regs->m_regLo <= RegKind::A31) {
                data = static_cast<u32>(regs->m_regLo) - static_cast<u32>(RegKind::A0);
            } else if (regs->m_regLo >= RegKind::B0 && regs->m_regLo <= RegKind::B31) {
                data = static_cast<u32>(regs->m_regLo) - static_cast<u32>(RegKind::B0);
            }
            return data;
        }

        auto imm = std::dynamic_pointer_cast<ImmediateOp>(op);
        if (imm) {
            data = imm->m_data;
            return data;
        }

        fatalMacro("指令的src1位解析错误！");
    }

    std::bitset<5> Generator::computeSrc2(std::shared_ptr<Operand> op) {
        std::bitset<5> data;
        auto reg = std::dynamic_pointer_cast<SingleRegOp>(op);
        if (reg) {
            if (reg->m_reg >= RegKind::A0 && reg->m_reg <= RegKind::A31) {
                data = static_cast<u32>(reg->m_reg) - static_cast<u32>(RegKind::A0);
            } else if (reg->m_reg >= RegKind::B0 && reg->m_reg <= RegKind::B31) {
                data = static_cast<u32>(reg->m_reg) - static_cast<u32>(RegKind::B0);
            }
            return data;
        }

        auto regs = std::dynamic_pointer_cast<DoubleRegOp>(op);
        if (regs) {
            if (regs->m_regLo >= RegKind::A0 && regs->m_regLo <= RegKind::A31) {
                data = static_cast<u32>(regs->m_regLo) - static_cast<u32>(RegKind::A0);
            } else if (regs->m_regLo >= RegKind::B0 && regs->m_regLo <= RegKind::B31) {
                data = static_cast<u32>(regs->m_regLo) - static_cast<u32>(RegKind::B0);
            }
            return data;
        }

        fatalMacro("指令的src2位解析错误！");
    }

    bool Generator::computeS(const std::string &funcUnit) {
        if (funcUnit.empty()) {
            return false;
        }

        return funcUnit[2] != '1';
    }

    bool Generator::computeX(std::shared_ptr<Operand> src2, bool s) {
        auto reg = std::dynamic_pointer_cast<SingleRegOp>(src2);
        if (reg) {
            if (reg->m_reg >= RegKind::A0 && reg->m_reg <= RegKind::A31) {
                return !s;
            } else if (reg->m_reg >= RegKind::B0 && reg->m_reg <= RegKind::B31) {
                return s;
            }
        }

        auto regs = std::dynamic_pointer_cast<DoubleRegOp>(src2);
        if (regs) {
            if (regs->m_regLo >= RegKind::A0 && regs->m_regLo <= RegKind::A31) {
                return !s;
            } else if (regs->m_regLo >= RegKind::B0 && regs->m_regLo <= RegKind::B31) {
                return s;
            }
        }
        fatalMacro("指令的x位解析错误！");
    }
}